<?php 
namespace lib;

class AssetHandler {
    private $basePath;
    private $mimeTypes = [
        'css'   => 'text/css',
        'js'    => 'application/javascript',
        'jpg'   => 'image/jpeg',
        'jpeg'  => 'image/jpeg',
        'png'   => 'image/png',
        'gif'   => 'image/gif',
        'svg'   => 'image/svg+xml',
        'woff'  => 'application/font-woff',
        'woff2' => 'application/font-woff2',
        'ttf'   => 'application/x-font-ttf',
        'eot'   => 'application/vnd.ms-fontobject',
        'json'  => 'application/json' // 添加 JSON 支持
    ];

    public function __construct($basePath) {
        $this->basePath = rtrim($basePath, '/');
    }

    private function getMimeType($filename) {
        $ext = strtolower(pathinfo($filename, PATHINFO_EXTENSION));
        return $this->mimeTypes[$ext] ?? 'application/octet-stream';
    }

    private function sendError($code, $message) {
        http_response_code($code);
        header('Content-Type: text/plain; charset=utf-8');
        echo $message;
        exit;
    }

    private function sendFile($file) {
        // 1. 清除所有之前的输出和头信息
        if (headers_sent()) {
            $this->sendError(500, 'Headers already sent');
            return;
        }

        while (ob_get_level()) {
            ob_end_clean();
        }

        // 2. 获取文件信息
        $mime = $this->getMimeType($file);
        $size = filesize($file);
        
        if ($size === false) {
            $this->sendError(500, 'Cannot get file size');
            return;
        }

        // 3. 设置基本响应头
        header('Content-Type: ' . $mime . '; charset=utf-8');
        header('Content-Length: ' . $size);
        header('Content-Transfer-Encoding: binary');
        header('Accept-Ranges: bytes');
        
        // 4. 缓存控制
        header('Cache-Control: public, max-age=31536000');
        header('Pragma: public');
        header('Expires: ' . gmdate('D, d M Y H:i:s \G\M\T', time() + 31536000));
        
        // 5. 安全头
        header('X-Content-Type-Options: nosniff');
        
        // 6. 明确指定内联显示
        header('Content-Disposition: inline; filename="' . basename($file) . '"');

        // 7. 输出文件内容
        if ($fp = fopen($file, 'rb')) {
            fpassthru($fp);
            fclose($fp);
        } else {
            $this->sendError(500, 'Cannot read file');
        }
        exit;
    }

    public function handle($path) {
        // 1. 基本安全检查
        if (empty($path) || strpos($path, '..') !== false) {
            $this->sendError(403, 'Invalid path');
            return;
        }

        // 2. 构建和验证文件路径
        $path = filter_var($path, FILTER_SANITIZE_URL);
        $fullPath = $this->basePath . '/' . ltrim($path, '/');
        $realPath = realpath($fullPath);
        
        if (!$realPath) {
            $this->sendError(404, 'File not found: ' . $fullPath);
            return;
        }

        // 3. 验证文件在允许的目录内
        if (strpos($realPath, realpath($this->basePath)) !== 0) {
            $this->sendError(403, 'Access denied');
            return;
        }

        // 4. 检查文件是否存在且可读
        if (!is_file($realPath) || !is_readable($realPath)) {
            $this->sendError(404, 'File not accessible');
            return;
        }

        // 5. 发送文件
        $this->sendFile($realPath);
    }
}